package cn.gemframe.oauth2.security.filter;

import cn.gemframe.config.security.GemAuthProperties;
import cn.gemframe.config.security.bean.GemUserDetails;
import cn.gemframe.constant.GemConstant;
import cn.gemframe.exception.status.GemErrorStatus;
import cn.gemframe.oauth2.bean.RequestPath;
import cn.gemframe.oauth2.service.GemPermitsService;
import cn.gemframe.response.ResultData;
import cn.gemframe.utils.GemJsonUtils;
import cn.gemframe.utils.GemSpringUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

@Data
@Slf4j
@EqualsAndHashCode(callSuper = false)
public class GemPermissionsValidateFilter extends OncePerRequestFilter {

	private Environment env;
	private TokenStore tokenStore;
	private GemAuthProperties gemAuthProperties;
	private ValueOperations<String, Object> valueOperations;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		//统一设置response
		response.setContentType(GemConstant.MediaType.JSON_UTF_8);

		String requestURI = request.getRequestURI();
		log.info("GemUserLoginValidateFilter================={}",requestURI);
		//读取权限开关配置
		boolean isOpenAuth = gemAuthProperties.isOpenAuth();
		boolean isAllAuth = gemAuthProperties.isAllAuth();
		boolean isChkImmed = gemAuthProperties.isChkImmed();

		log.info("=========权限校验开关========{}",isOpenAuth);
		//开启权限校验
		if(isOpenAuth){
			//拦截全部
			log.info("=========拦截全部开关========{}",isAllAuth);
			if (isAllAuth) {
				boolean checkHavePermissions = checkHavePermissions(isChkImmed, requestURI);
				if (checkHavePermissions) {
					filterChain.doFilter(request, response);
				} else {
					response.setStatus(HttpStatus.UNAUTHORIZED.value());
					response.getWriter().write(GemJsonUtils.objectToJson(ResultData.getResultWithCode(GemErrorStatus.NOT_PERMISSIONS)));
					return;
				}
			}else {
				String noRelease = UUID.randomUUID().toString();
				if (requestURI.contains(RequestPath.Access.SWAGGER)
						|| requestURI.equals(RequestPath.Access.APIDOCS)
						|| noRelease.contains(requestURI)
						|| requestURI.contains(noRelease)
				) {
					filterChain.doFilter(request, response);
				}else{
					boolean checkHavePermissions = checkHavePermissions(isChkImmed, requestURI);
					if (checkHavePermissions) {
						filterChain.doFilter(request, response);
					} else {
						response.setStatus(HttpStatus.UNAUTHORIZED.value());
						response.getWriter().write(GemJsonUtils.objectToJson(ResultData.getResultWithCode(GemErrorStatus.NOT_PERMISSIONS)));
						return;
					}
				}
			}

		}else{
			filterChain.doFilter(request, response);
		}
	}




	/***
	 * 是否拥有相关权限
	 * @param isChkImmed 是否校验授权日期
	 * @param requestURI 请求路径
	 * @return
	 */
	public boolean checkHavePermissions(boolean isChkImmed, String requestURI) {
		log.info("=========实时验证开关========{}，开：去数据库校验；关：去缓存校验",isChkImmed);
		//开启实时验证
		if (isChkImmed) {
		    //去数据库读取
			GemPermitsService gemFramePermissionsService = GemSpringUtil.getBean(GemPermitsService.class);
			if (gemFramePermissionsService == null) {
				return false;
			}
			List<String> permitsList = gemFramePermissionsService.permitsList();
			if (permitsList == null || permitsList.size() == 0) {
				return false;
			}
			if (!permitsList.contains(requestURI)) {
				return false;
			}
			return true;
		} else {
		    //从session获取
			GemUserDetails user = GemUserDetails.getUserData();
			if (user == null) {
				return false;
			}
			List<String> permitsList = user.getPermits();
			if (permitsList == null || permitsList.size() == 0) {
				return false;
			}
			if (!permitsList.contains(requestURI)) {
				return false;
			}
			return true;
		}
	}
}
